package com.liaogui.oss;

import cn.hutool.core.util.IdUtil;
import com.liaogui.oss.domain.FileInfo;
import com.liaogui.oss.domain.R;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author liaogui
 * @date 2025/1/21 22:00
 */
@RestController
@RequestMapping("/file")
@RequiredArgsConstructor
public class FileController {
    private final S3Client s3Client;

    @Value("${s3.bucket}")
    private String bucket;

    @Value("${s3.uri}")
    private String uri;

    /**
     * 单个附件上传
     *
     * @param file 文件
     * @return {@link R}<{@link FileInfo}>
     * @throws IOException io异常
     */
    @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public R<FileInfo> upload(@RequestPart("file") MultipartFile file) throws IOException {
        // TODO 也可使用数据库主键来标识文件Id
        String fileId = IdUtil.getSnowflakeNextIdStr();
        String originalFilename = file.getOriginalFilename();
        String fileExtension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        String key = fileId + fileExtension;
        PutObjectResponse putObjectResponse = s3Client.putObject(PutObjectRequest.builder()
                        .bucket(bucket)
                        .key(key)
                        .build(),
                RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
        FileInfo fileInfo = new FileInfo();
        fileInfo.setFileName(originalFilename);
        fileInfo.setKey(key);
        fileInfo.setFileId(fileId);
        fileInfo.setPath(uri + "/" + bucket + "/" + key);
        if (putObjectResponse.sdkHttpResponse().statusCode() == 200) {
            return R.ok(fileInfo);
        }
        return R.fail("上传失败");
    }


    /**
     * 多个附件上传
     *
     * @param files 文件
     * @return {@link R}<{@link FileInfo}>
     * @throws IOException io异常
     */
    @PostMapping(value = "/uploadFileList", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public R<List<FileInfo>> uploadFileList(@RequestPart("files") List<MultipartFile> files) throws IOException {
        List<FileInfo> fileInfos = new ArrayList<>();
        String path = uri + "/" + bucket + "/";
        for (MultipartFile file : files) {
            // TODO 也可使用数据库主键来标识文件Id
            String fileId = IdUtil.getSnowflakeNextIdStr();
            String originalFilename = file.getOriginalFilename();
            String fileExtension = "";
            if (originalFilename != null && originalFilename.contains(".")) {
                fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            }
            String key = fileId + fileExtension;
            PutObjectResponse putObjectResponse = s3Client.putObject(PutObjectRequest.builder()
                            .bucket(bucket)
                            .key(key)
                            .build(),
                    RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
            FileInfo fileInfo = new FileInfo();
            fileInfo.setFileName(originalFilename);
            fileInfo.setKey(key);
            fileInfo.setFileId(fileId);
            fileInfo.setPath(path + key);
            if (putObjectResponse.sdkHttpResponse().statusCode() == 200) {
                fileInfos.add(fileInfo);
            }
        }
        return R.ok(fileInfos);
    }

    /**
     * 删除单个附件
     *
     * @param key 上传文件返回值key
     * @return {@link DeleteObjectResponse}
     */
    @DeleteMapping("/{key}")
    public R<Void> delete(@PathVariable("key") String key) {
        DeleteObjectResponse deleteObjectResponse = s3Client.deleteObject(DeleteObjectRequest.builder()
                .bucket(bucket)
                .key(key)
                .build());
        if (deleteObjectResponse.sdkHttpResponse().statusCode() == 204) {
            return R.ok("删除成功");
        }
        return R.fail("删除失败");
    }
}
